module service.GroupService;

import repository;
import model;
import client.MsgServerClient;
import msgtrans;
import hunt.logging;
import message.Constants;
import message.MsgDefine;
import std.conv : to;
import core.stdc.time;
import bootstrap.DatabaseBootstrap;

import hunt.framework;

class GroupService {

  static int addGroup(CreateGroupREQ req,message.MsgDefine.User[] users)
  {
      auto em = defaultEntityManager();
      em.getTransaction().begin();
      GroupRepository repo = new GroupRepository;
      int id =  repo.addGroup(req,em);
      foreach(message.MsgDefine.User u ; users)
      {
        GroupService.addGroupUser(u.id, id, u.nickname,em);
      }
      em.getTransaction().commit();
      em.close();
      return id;
  }

  static void groupInvite(InviteGroup req ,string destination)
  {
      auto em = defaultEntityManager();
      em.getTransaction().begin();
      GroupService.addGroupUser(destination, to!int(req.groupId), req.aliasName, em);
      em.getTransaction().commit();
      em.close();
  }

  static void addGroupUser(string userId, int groupId, string nickname ,EntityManager em)
  {
      GroupUserRepository repo = new GroupUserRepository;
      repo.addGroupUser(userId,groupId,nickname,em);
  }

  static void addGroupApply(ApplyGroup req,uint type)
  {
      GroupApplyRepository repo = new GroupApplyRepository;
      repo.addGroupApply(req,type);
  }

  static void updateGroupApplyStatus(string groupId, string fromId, string toId, bool succeeded)
  {
      GroupApplyRepository repo = new GroupApplyRepository;
      repo.updateGroupApply(groupId, fromId, toId, succeeded);
  }

  static void setValidation(uint validation, string groupId, string manager)
  {
       GroupRepository repo = new GroupRepository;
       repo.setValidation(validation,groupId,manager);
  }

  static void setGroupName(string groupId, string groupName)
  {
      GroupRepository repo = new GroupRepository;
      repo.setGroupName(groupId,groupName);
  }

  static JoinGroup selectGroupInfo(string groupId, string fromId)
  {
    import message.MsgDefine;
    auto userRepo = new UserRepository();
    auto groupRepo = new GroupRepository();
    auto groupUserRepo = new GroupUserRepository();
    User[] members;
    ChatGroup groupInfo = groupRepo.findByUid(to!int(groupId));

    GroupUser[] users = groupUserRepo.findAllByID(to!int(groupId));
    foreach(GroupUser u ; users)
    {
      auto user = userRepo.findById(u.userId);
      if(user is null)
      {
        logWarningf("not this userinfo %d" , u.userId);
        continue;
      }
      auto resUser = toUser(user);
      members ~= resUser;
    }

    JoinGroup res = new JoinGroup();
    res.groupId = groupId;
    res.aliasName = groupInfo.aliasName;
    res.validation = groupInfo.validation;
    res.notice = groupInfo.notice;
    res.destination = fromId;
    res.member = members;
    return res;
  }

  static void deleteGroupUser(string userId, string groupId)
  {
    auto groupUserRepo = new GroupUserRepository();
    bool changeManger = false;
    bool deleteGroup = false;
    uint newManagerId = 0;
    auto em = defaultEntityManager();
    if(isCreator(userId,groupId))
    {
       changeManger = true;
       newManagerId = selectManager(groupId);
       if(newManagerId == 0)
       {
          deleteGroup = true;
       }
    }

    em.getTransaction().begin();
    if (changeManger)
    {
        if(deleteGroup)
        {
          GroupService.deleteGroup(groupId,em);
        }
        else
        {
          GroupService.changeManager(groupId, userId, em);
        }
    }
    groupUserRepo.deleteGroupUser(groupId,userId,em);

    em.getTransaction().commit();
    em.close();
  }


  static void deleteGroup(string groupId, EntityManager em)
  {
      auto groupRep = new GroupRepository;
      groupRep.deleteGroup(groupId,em);
  }

  static void changeManager(string groupId, string userId, EntityManager em)
  {
      auto groupRep = new GroupRepository;
      groupRep.changeManager(groupId, userId, em);
  }

  static void cancelGroup(string fromId, string groupId)
  {
      //if (!isCreator(fromId, groupId))
      //{
      //    logErrorf("user %s is not group creator %s", fromId, groupId);
      //    return;
      //}
      //auto groupUserRepo = new GroupUserRepository;
      //auto groupRepo = new GroupRepository;
      //groupUserRepo.deleteAllGroupUser(groupId);
      //groupRepo.deleteGroup(groupId);
  }

  static bool isCreator(string fromId, string groupId)
  {
    auto groupRepo = new GroupRepository;
    return groupRepo.isCreator(fromId, groupId);
  }

  static uint selectManager(string groupId)
  {
    auto groupRepo = new GroupUserRepository;
    return groupRepo.selectManager(groupId);
  }

  static bool needValidation(string groupId, string userId , out string manager)
  {
     auto groupRepo = new GroupRepository;
     return groupRepo.needValidation(groupId, userId, manager);
  }

  static bool isExist(string uid , string groupId)
  {
      auto groupRepo = new GroupUserRepository;
      return groupRepo.isExist(to!uint(uid),to!uint(groupId));
  }

  static void updateGroupInfo(UpdateGroupInfo req)
  {
      if (isCreator(req.fromId,req.groupId))
      {
        auto groupRepo = new GroupRepository;
        groupRepo.updateGroupInfo(req);
      }
      return;
  }


  static GroupInfo[] getAllGroupMember(string userId)
  {
      GroupInfo[] rt;
      GroupUserRepository groupUserRepo = new GroupUserRepository;
      GroupRepository groupRepo = new GroupRepository;
      GroupUser[] gps = groupUserRepo.findAllByUserId(to!uint(userId));
      foreach(GroupUser g ; gps)
      {
          GroupInfo ct = new GroupInfo;
          ct.groupId = to!int(g.groupId);
          auto groupInfo = groupRepo.findByUid(ct.groupId);
          ct.groupName = groupInfo.aliasName;
          ct.validation = groupInfo.validation;
          GroupUser[] mbs = groupUserRepo.findAllByID(ct.groupId);
          foreach(GroupUser m ; mbs)
          {
            ct.memberId ~= to!int(m.userId);
          }
          rt ~= ct;
      }
      return rt;
  }


}

